package com.artisan.domain.service;

import com.artisan.domain.dto.AccountDto;
import com.artisan.domain.dto.PageDto;
import com.artisan.domain.entity.MAccount;
import com.artisan.domain.entity.MRole;
import com.artisan.domain.entity.QMAccount;
import com.artisan.domain.entity.QMRole;
import com.artisan.domain.repository.AccountRepository;
import com.artisan.domain.repositoryInterface.IAccountRepository;
import com.artisan.domain.serviceInterface.IAccountService;
import com.artisan.util.MD5Util;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.hibernate.mapping.Array;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 账户业务泪
 */
@Service
public class AccountService implements IAccountService {
    @Autowired
    private IAccountRepository jpaAccountRepository;
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Override
    public Page<AccountDto> findList(String userName, String provinceName, String cityName, String areaName, String streetName, String communityName, int pageIndex, int pageSize) {
        Pageable pageable = new QPageRequest(pageIndex, pageSize);  //分页信息

        QMAccount account = QMAccount.mAccount;
        QMRole role = QMRole.mRole;
        //初始化组装条件(类似where 1=1)
        Predicate predicate = account.isNotNull().or(account.isNull());
        //执行动态条件拼装
        predicate = userName == null || userName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.userName.like(userName));
        predicate = provinceName == null || provinceName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.provinceName.eq(provinceName));
        predicate = cityName == null || cityName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.cityName.eq(cityName));
        predicate = areaName == null || areaName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.areaName.eq(areaName));
        predicate = streetName == null || streetName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.streetName.eq(streetName));
        predicate = communityName == null || communityName.isEmpty() ? predicate : ExpressionUtils.and(predicate, account.communityName.eq(communityName));

        QueryResults<Tuple> result = this.accountRepository.find(predicate)
                    .offset(pageable.getOffset())   //起始页
                .limit(pageable.getPageSize())  //每页大小
                .fetchResults();

        List<AccountDto> dtos = new ArrayList<>();
        result.getResults().forEach(p -> {
            AccountDto dto = new AccountDto();
            dto.setUserName(p.get(account).getUserName());
            dto.setProvinceName(p.get(account).getProvinceName());
            dto.setCityName(p.get(account).getCityName());
            dto.setAreaName(p.get(account).getAreaName());
            dto.setStreetName(p.get(account).getStreetName());
            dto.setCommunityName(p.get(account).getCommunityName());
            dto.setRoleName(p.get(role).getName());
            dto.setAddDate(p.get(account).getAddDate());
            dto.setLastLoginDate(p.get(account).getLastLoginDate());
            dto.setStatus(p.get(account).getStatus());
            dtos.add(dto);

        });
        Page<AccountDto> page=new PageImpl(dtos,pageable,result.getTotal());
        return page;
    }

    @Override
    public int add(AccountDto dto) {

        MAccount model = dto.convert();
        model.setId(0);
        model.setNickName("");
        model.setStatus(1);
        model.setAddDate(System.currentTimeMillis());
        model.setLastLoginDate(0);
        model.setPassword(MD5Util.getMD5(dto.getPassword()));

        this.jpaAccountRepository.saveAndFlush(model);
        return model.getId();

    }

    @Override
    public AccountDto find(int id) {
        QMAccount account = QMAccount.mAccount;
        QMRole role = QMRole.mRole;
        Predicate predicate = account.id.eq(id);

        Tuple result = this.accountRepository.find(predicate).fetchFirst();

        AccountDto dto = new AccountDto();
        dto.setId(result.get(account).getId());
        dto.setUserName(result.get(account).getUserName());
        dto.setPassword(result.get(account).getPassword());
        dto.setProvinceName(result.get(account).getProvinceName());
        dto.setCityName(result.get(account).getCityName());
        dto.setAreaName(result.get(account).getAreaName());
        dto.setStreetName(result.get(account).getStreetName());
        dto.setCommunityName(result.get(account).getCommunityName());
        dto.setRoleName(result.get(role).getName());
        dto.setRoleId(result.get(account).getRoleId());
        dto.setAddDate(result.get(account).getAddDate());
        dto.setLastLoginDate(result.get(account).getLastLoginDate());
        dto.setStatus(result.get(account).getStatus());

        return dto;
    }

    @Override
    public boolean update(AccountDto dto) {
        MAccount model = this.jpaAccountRepository.findById(dto.getId()).get();
        model.setAreaName(dto.getAreaName());
        model.setCityName(dto.getCityName());
        model.setCommunityName(dto.getCommunityName());
        model.setProvinceName(dto.getProvinceName());
        model.setRoleId(dto.getRoleId());
        model.setStreetName(dto.getStreetName());
        model.setUserName(dto.getUserName());
        if (dto.getPassword()!=null && !dto.getPassword().isEmpty()) {
            model.setPassword(MD5Util.getMD5(dto.getPassword()));
        }

        this.jpaAccountRepository.saveAndFlush(model);
        return true;
    }

    @Override
    public boolean delete(int id) {
        this.jpaAccountRepository.deleteById(id);
        return true;
    }

    @Override
    public boolean updateStatus(String ids, int status) {
        int[] idss = Arrays.stream(ids.split(",")).mapToInt(Integer::parseInt).toArray();
        for (int id : idss) {
            MAccount model = this.jpaAccountRepository.findById(id).orElseGet(()-> new MAccount());
            if (model.getId() != 0) {
                model.setStatus(status);
                this.jpaAccountRepository.save(model);
            }


        }
        this.jpaAccountRepository.flush();

        return true;
    }
}
